package com.zhl.common.aspect;


import com.zhl.common.annotation.NoRepeatSubmit;
import com.zhl.common.vo.Result;
import com.zhl.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.UUID;

/**
 * 防止表单重复提交 切面类
 *
 * @author mzk
 */
@Aspect
@Component
@Slf4j
public class RepeatSubmitAspect {

    @Autowired
    private RedisUtil redisUtil;

    @Pointcut("@annotation(noRepeatSubmit)")
    public void Pointcut(NoRepeatSubmit noRepeatSubmit) {
    }

    /*//前置通知
    @Before("Pointcut()")
    public void beforeMethod(JoinPoint joinPoint) {
        log.info("调用了前置通知");

    }

    //@After: 后置通知
    @After("Pointcut()")
    public void afterMethod(JoinPoint joinPoint) {
        log.info("调用了后置通知");
    }

    //@AfterRunning: 返回通知 rsult为返回内容
    @AfterReturning(value = "Pointcut()", returning = "result")
    public void afterReturningMethod(JoinPoint joinPoint, Object result) {
        log.info("调用了返回通知");
    }

    //@AfterThrowing: 异常通知
    @AfterThrowing(value = "Pointcut()", throwing = "e")
    public void afterReturningMethod(JoinPoint joinPoint, Exception e) {
        log.info("调用了异常通知");
    }*/

    //@Around：环绕通知
    @Around("Pointcut(noRepeatSubmit)")
    public Object Around(ProceedingJoinPoint pjp, NoRepeatSubmit noRepeatSubmit) throws Throwable {
        log.info("around执行方法之前");
        int lockSeconds = noRepeatSubmit.lockTime();
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        String token = request.getHeader("authorization");
        String path = request.getServletPath();
        String key = token + path;
        String value = UUID.randomUUID().toString();

        boolean lock = redisUtil.getLock(key, value, lockSeconds);
        // 获取redis锁
        if (lock) {
            // 获取锁 执行进程
            Object result;
            try {
                result = pjp.proceed();
            } finally {
                // 解锁
                redisUtil.releaseLock(key);
            }
            log.info("around执行方法之后");
            return result;
        } else {
            log.info("重复请求,请稍后再试。。。");
            return Result.error(200, "重复请求,请稍后再试");
        }
    }
}
